package br.zeos;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;

public class ZSql {

    public static enum Tipos {

        String,
        Integer,
        Float,
        Calendar,
        Blob
    };

    private ZTable tabela;
    private HashMap<String, String> Data = new HashMap<String, String>();
    private HashMap<String, String> P = new HashMap<String, String>();

    public ZSql(ZTable tabela) {
        this.tabela = tabela;
        for (Map.Entry<String, Tipos> entrySet : tabela.getFields().entrySet()) {
            String campo = entrySet.getKey();
            Tipos tipo = entrySet.getValue();
            this.putField(campo.toUpperCase(), "", tipo);
        }
    }

    public void putField(String Field, String Value) {
        this.putField(Field.toUpperCase(), Value, this.getTabela().getFields().get(Field.toUpperCase()));
    }

    public void putField(String Field, String Value, Tipos tipo) {
        
        Value = Value.replace("'", "");
        switch (tipo) {
            case String:
                Value = "'" + Value + "'";
                break;
            case Float:
                Value = Value.trim();
                Value = Value.replaceAll(Pattern.quote("\\'"), "");
                if (Value.contains(".") || Value.contains(",")) {
                    int menor = (Value.length() - ((Value.lastIndexOf(".") >= Value.lastIndexOf(",")) ? Value.lastIndexOf(".") : Value.lastIndexOf(","))) - 1;
                    Value = Value.replaceAll(Pattern.quote("."), "");
                    Value = Value.replaceAll(Pattern.quote(","), "");
                    Value = Value.substring(0, Value.length() - menor) + "." + Value.substring(Value.length() - menor);
                    if (menor == 1) {
                        Value += "0";
                    }
                } else {
                    Value += ".00";
                }
                break;
            case Integer:
                Value = Value.trim();
                if (Value.isEmpty()) {
                    Value = "0";
                }
//                Value = Value.replaceAll("\\D", "");
                break;
            case Calendar:
                Boolean nulo = false;
                if (!Value.isEmpty()) {
                    try {
                        String formato = "";
                        if (Value.split("[0-9]{4}\\-").length > 1) {
                            formato = "yyyy-MM-dd";
                        } else {
                            formato = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.MEDIUM, java.util.Locale.getDefault())).toPattern();
                        }
                        if (Value.split("\\s[0-9]{2}\\:").length > 1) {
                            formato += " HH:mm:ss";
                        }
                        SimpleDateFormat formatador = new SimpleDateFormat(formato);
                        try {

                            Date d = formatador.parse(Value);
                            SimpleDateFormat f2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            Value = f2.format(d);
                        } catch (Exception e) {
//                            e.printStackTrace();
                            nulo = true;
                        }
                    } catch (Exception e) {
//                        e.printStackTrace();
                        nulo = true;
                    }
                }
                if (nulo) {
                    SimpleDateFormat f3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String valor = f3.format(new Date());
                    Value = "'" + valor + "'";
                } else {
                    Value = "'" + Value + "'";
                }
                break;
            case Blob:
                String protoloco = this.getTabela().getConnection().getProtocol();
                if (protoloco.equalsIgnoreCase("mysql")) {
                    Value = "'0x" + Value + "'";
                } else if (protoloco.equalsIgnoreCase("postgresql")) {
                    Value = "decode('" + Value + "','hex')";
                } else if (protoloco.equalsIgnoreCase("sqlite")) {
                    Value = "X'" + Value + "'";
                } else {
                    Value = "'" + Value + "'";
                }
                break;
        }
        this.Data.put(Field.toUpperCase(), Value);
    }

    public void putParameter(String Field, String Value, Tipos tipo) {
        Value = Value.replace("'", "");
        switch (tipo) {
            case String:
                Value = "'" + Value + "'";
                break;
            case Float:
                Value = Value.trim();
                Value = Value.replaceAll(Pattern.quote("\\'"), "");
                if (Value.contains(".") || Value.contains(",")) {
                    Value = Value.replaceAll(Pattern.quote("."), "");
                    Value = Value.replaceAll(Pattern.quote(","), "");
                    Value = Value.substring(0, Value.length() - 2) + "." + Value.substring(Value.length() - 2);
                } else {
                    Value += ".00";
                }
                break;
            case Integer:
                Value = Value.trim();
                if (Value.isEmpty()) {
                    Value = "0";
                }
                break;
            case Calendar:
                Boolean nulo = false;
                if (!Value.isEmpty()) {
                    try {
                        String formato = "";
                        if (Value.split("[0-9]{4}\\-").length > 1) {
                            formato = "yyyy-MM-dd";
                        } else {
                            formato = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.MEDIUM, java.util.Locale.getDefault())).toPattern();
                        }
                        if (Value.split("\\s[0-9]{2}\\:").length > 1) {
                            formato += " HH:mm:ss";
                        }
                        SimpleDateFormat formatador = new SimpleDateFormat(formato);
                        try {

                            Date d = formatador.parse(Value);
                            SimpleDateFormat f2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            Value = f2.format(d);
                        } catch (Exception e) {
//                            e.printStackTrace();
                            nulo = true;
                        }
                    } catch (Exception e) {
//                        e.printStackTrace();
                        nulo = true;
                    }
                }
                if (nulo) {
                    SimpleDateFormat f3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String valor = f3.format(new Date());
                    Value = "'" + valor + "'";
                } else {
                    Value = "'" + Value + "'";
                }
                break;
            case Blob:
                String protoloco = this.getTabela().getConnection().getProtocol();
                if (protoloco.equalsIgnoreCase("mysql")) {
                    Value = "'0x" + Value + "'";
                } else if (protoloco.equalsIgnoreCase("postgresql")) {
                    Value = "decode('" + Value + "','hex')";
                } else if (protoloco.equalsIgnoreCase("sqlite")) {
                    Value = "X'" + Value + "'";
                } else {
                    Value = "'" + Value + "'";
                }
                break;
        }
        this.P.put(Field.toUpperCase(), Value);
    }

    public ZTable getTabela() {
        return tabela;
    }

    public void setTabela(ZTable tabela) {
        this.tabela = tabela;
    }

    public HashMap<String, String> getData() {
        return Data;
    }

    public void Insert() {
        String retorno = "";
        retorno = "INSERT INTO " + this.getTabela().getTableName() + " (";
        int contador = 0;
        for (Map.Entry<String, String> sis1 : Data.entrySet()) {
            String chave = sis1.getKey();
            Object valor = sis1.getValue();
            if (valor.toString().isEmpty() || chave.equalsIgnoreCase(this.getTabela().getPrimaryKeyName())) {
                contador++;
                continue;
            }
            if (contador == Data.size() - 1) {
                retorno += chave.toUpperCase();
            } else {
                retorno += chave.toUpperCase() + ",";
            }
            contador++;
        }
        retorno += ") values (";
        contador = 0;
        for (Map.Entry<String, String> sis1 : Data.entrySet()) {
            String chave = sis1.getKey();
            Object valor = sis1.getValue();
            if (valor.toString().isEmpty() || chave.equalsIgnoreCase(this.getTabela().getPrimaryKeyName())) {
                contador++;
                continue;
            }
            if (contador == Data.size() - 1) {
                retorno += valor;
            } else {
                retorno += valor + ",";
            }
            contador++;
        }
        retorno += ")";
        this.getTabela().getConnection().DirectExec(retorno);
    }

    public void Update(String where) {
        String retorno = "";
        retorno = "UPDATE " + this.getTabela().getTableName() + " SET ";
        int contador = 0;
        for (Map.Entry<String, String> sis1 : Data.entrySet()) {
            String chave = sis1.getKey();
            Object valor = sis1.getValue();
            if (contador == Data.size() - 1) {
                retorno += chave.toUpperCase() + "=" + valor.toString();
            } else {
                retorno += chave.toUpperCase() + "=" + valor.toString() + ",";
            }
            contador++;
        }
        retorno += " WHERE ";
        for (Map.Entry<String, String> entrySet : P.entrySet()) {
            String chave = entrySet.getKey();
            String valor = entrySet.getValue();
            where = where.replaceAll(chave.toUpperCase(), valor);
        }
        retorno += where;
        this.getTabela().getConnection().DirectExec(retorno);
    }

    public void Delete(String where) {
        String retorno = "";
        retorno = "DELETE FROM " + this.getTabela().getTableName() + " WHERE ";
        for (Map.Entry<String, String> entrySet : P.entrySet()) {
            String chave = entrySet.getKey();
            String valor = entrySet.getValue();
            where = where.replaceAll(chave.toUpperCase(), valor);
        }
        retorno += where;
        this.getTabela().getConnection().DirectExec(retorno);
    }

    public ArrayList<HashMap<String, String>> Select() {
        return Select("", -1, -1);
    }

    public ArrayList<HashMap<String, String>> Select(String sql) {
        return Select(sql, -1, -1);
    }

    public ArrayList<HashMap<String, String>> Select(String where, int limit, int offset) {
        String retorno = "";
        retorno = "SELECT ";
        int contador = 0;
        for (Map.Entry<String, String> sis1 : Data.entrySet()) {
            String chave = sis1.getKey();
            Object valor = sis1.getValue();
            if (contador == Data.size() - 1) {
                retorno += chave.toUpperCase();
            } else {
                retorno += chave.toUpperCase() + ",";
            }
            contador++;
        }
        retorno += " FROM " + this.getTabela().getTableName();
        if (!where.isEmpty()) {
            retorno += " WHERE ";
            for (Map.Entry<String, String> entrySet : P.entrySet()) {
                String chave = entrySet.getKey();
                String valor = entrySet.getValue();
                where = where.replaceAll(chave, valor);
            }
            retorno += where;
        }
        String paginador = "";
        if (!(limit == -1 && offset == -1)) {
            if (limit > -1) {
                paginador += " LIMIT " + limit;
            }
            if (offset > -1) {
                paginador += " OFFSET " + offset;
            }
        }
        retorno += paginador;
        return this.getTabela().getConnection().DirectQuery(retorno);
    }
}
